﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using MimeKit;
using ShortLink.Common.Helper;
using ShortLink.Common.Redis;
using ShortLink.Common.Results;
using ShortLink.Common.Settings;
using SkiaSharp;
using MimeKit;
using MailKit.Net.Smtp;


namespace SL_Account.Services.Impl
{
    public class NotifyService : INotifyService
    {
        private readonly IRedisAccessor redisAccessor;
        private readonly IHttpContextAccessor httpContextAccessor;
        public NotifyService(IRedisAccessor redisAccessor, IHttpContextAccessor httpContextAccessor)
        {
            this.redisAccessor = redisAccessor;
            this.httpContextAccessor = httpContextAccessor;
        }

        public async Task<JsonData> GenerateCode()
        {
            var code = GenerateRandomCode();
            var image = GenerateCaptchaImage(code);
            var key = GetCaptchaRedisKey();
            await redisAccessor.SetAsync(key,code,TimeSpan.FromMinutes(5));
            return JsonData.BuildSuccess(image);
        }

        private string GenerateRandomCode() 
        {
            var codeLen = int.Parse(AppSettings.GetValue("CodeLen"));
            int maxValue = (int)Math.Pow(10, codeLen);
            var code = Random.Shared.Next(0, maxValue).ToString($"D{codeLen}");
            return code;
        }

        private static string GetClientIp(HttpContext httpContext)
        {
            string? ip = httpContext.Connection.RemoteIpAddress?.ToString();

            // 处理代理 IP
            if (httpContext.Request.Headers.TryGetValue("X-Forwarded-For", out var forwardedFor))
            {
                ip = forwardedFor.FirstOrDefault()?.Split(',')[0]?.Trim();
            }

            return ip ?? "Unknown";
        }

        private static string GetBrowserFingerprint(HttpContext httpContext)
        {
            string userAgent = httpContext.Request.Headers["User-Agent"].ToString();
            return userAgent;
        }
        private static byte[] GenerateCaptchaImage(string code)
        {
            int width = 120, height = 50;

            using var bitmap = new SKBitmap(width, height);
            using var canvas = new SKCanvas(bitmap);
            canvas.Clear(SKColors.White);

            // 生成字体
            using var paint = new SKPaint
            {
                Color = SKColors.Black,
                TextSize = 32,
                IsAntialias = true,
                Typeface = SKTypeface.Default // 选择默认字体（无需安装 Arial）
            };

            // 绘制验证码
            canvas.DrawText(code, 20, 35, paint);

            // 添加干扰线
            using var linePaint = new SKPaint { Color = SKColors.Gray, StrokeWidth = 2 };
            Random rand = new Random();
            for (int i = 0; i < 5; i++)
            {
                float x1 = rand.Next(0, width);
                float y1 = rand.Next(0, height);
                float x2 = rand.Next(0, width);
                float y2 = rand.Next(0, height);
                canvas.DrawLine(x1, y1, x2, y2, linePaint);
            }

            // 保存图片到字节数组
            using var image = SKImage.FromBitmap(bitmap);
            using var data = image.Encode(SKEncodedImageFormat.Png, 100);
            return data.ToArray();
        }

        private string GetCaptchaRedisKey() 
        {
            //生成redis
            var ip = GetClientIp(httpContextAccessor.HttpContext);
            var browser = GetBrowserFingerprint(httpContextAccessor.HttpContext);
            var key = MD5Helper.ComputeMD5(ip + "." + browser);
            return key;
        }

        public async Task<JsonData> SendEmail(string toEmail,string key)
        {
        
            var rdKey = GetCaptchaRedisKey();
            var value = await redisAccessor.GetAsync<string>(rdKey);
            if (string.IsNullOrEmpty(value) || !value.Equals(key)) 
            {
                return JsonData.BuildError("验证码有误,请重新刷新!");
            }

            var code = GenerateRandomCode();
            var message = new MimeMessage();
            message.From.Add(new MailboxAddress("Sender", AppSettings.GetValue("EmailSettings:SmtpUser")));
            message.To.Add(new MailboxAddress("Recipient", toEmail));
            message.Subject = "SL验证码";

            await redisAccessor.SetAsync(toEmail, code, TimeSpan.FromMinutes(10));
            var bodyBuilder = new BodyBuilder
            {
                TextBody = $"您的验证码:{code},有效期10分钟!"
            };
            message.Body = bodyBuilder.ToMessageBody();

            using (var client = new SmtpClient())
            {
                await client.ConnectAsync(AppSettings.GetValue("EmailSettings:SmtpServer"), int.Parse(AppSettings.GetValue("EmailSettings:SmtpPort")), false);
                await client.AuthenticateAsync(AppSettings.GetValue("EmailSettings:SmtpUser"), AppSettings.GetValue("EmailSettings:SmtpPassword"));
                await client.SendAsync(message);
                await client.DisconnectAsync(true);
            }
            return JsonData.BuildSuccess("ok");
        }
    }
}
